#ifndef FFTIMER_H
#define FFTIMER_H

#include <functional>
#include <thread>
#include <chrono>
#include<iostream>
#include <atomic>
#include <condition_variable>
#include<QMetaObject>
#include<iomanip>

extern "C"{
#include<libavformat/avformat.h>
}

class FFVFrameQueue;
class FFPlayerContext;
class FFVRender;
class FFVideoPars;
class FFVDecoder;
class FFGLRenderWidget;
class FFTimer {
public:
    FFTimer();
    ~FFTimer();

    void init(FFVDecoder*vDecoder_, FFVFrameQueue* frmQueue_,FFVRender* vRender_,FFGLRenderWidget*renderWidget_);
    void start();
    void wait();
    void stop();
    void pause();
    void close();
    void wakeAllThread();
    void setSpeed(float speed_);

private:
    void work();
    void copyYUV(AVFrame* frame);
    int optimizeSync(int64_t delay, int64_t standardInterval);

    void setTimerInterval(std::chrono::milliseconds interval_);
    void setTimerInterval(double interval_);
    void setTimerInterval(int64_t interval_);

    void initVideo();
    void playVideo();

private:
    std::chrono::microseconds interval;

    std::thread timerTread;
    bool m_stop;

    FFVFrameQueue* frmQueue = nullptr;
    FFVDecoder* vDecoder = nullptr;
    FFVideoPars* vPars = nullptr;
    FFPlayerContext* playerCtx = nullptr;
    FFVRender* vRender = nullptr;

    int64_t standardInterval;
    int64_t syncThreshold;
    int totalSec = -1;

    std::mutex mutex;
    std::condition_variable cond;
    std::condition_variable pauseCond;
    std::mutex pauseMutex;

    std::atomic<bool>seekFlag;
    std::atomic<bool>pauseFlag;
    uint8_t* yBuf = nullptr;
    uint8_t* uBuf = nullptr;
    uint8_t* vBuf = nullptr;

    std::atomic<bool>speedFlag;
    float speed;
    float speedFactor;

    FFGLRenderWidget*renderWidget = nullptr;

};

#endif // FFTIMER_H
